package com.cd.university.service.impl;

import com.cd.university.common.RestResult;
import com.cd.university.common.UniversityConstants;
import com.cd.university.common.utils.SpringUtil;
import com.cd.university.db.mapper.AwardedExamineMapper;
import com.cd.university.db.mapper.AwardedMapper;
import com.cd.university.db.pojo.Awarded;
import com.cd.university.db.pojo.AwardedExamine;
import com.cd.university.db.pojo.Message;
import com.cd.university.service.MessageService;
import com.cd.university.service.ProjectExamineService;
import com.cd.university.service.abs.AbstractAchievementProcessor;
import com.cd.university.vo.AwardedExamineVo;
import com.cd.university.vo.ProjectExamineVo;
import com.cd.university.vo.UserVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 陈栋
 * @create 2021/11/9 21:25
 */
@Transactional(rollbackFor = Exception.class)
@Component
public class AwardedProcessor extends AbstractAchievementProcessor<Awarded, AwardedExamineVo> {

    @Autowired
    private AwardedMapper awardedMapper;

    @Autowired
    private AwardedExamineMapper awardedExamineMapper;

    @Autowired
    private MessageService messageService;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public RestResult approvedAchievement(Integer aeId, Integer reviewerId) {
        AwardedExamine examine = new AwardedExamine();
        examine.setExamineStatus("审核通过");
        examine.setAeId(aeId);
        examine.setReviewerId(reviewerId);
        examine.setApplyTime(new Date(System.currentTimeMillis()));

        AwardedExamine awardedExamine = awardedExamineMapper.selectByPrimaryKey(aeId);
        examine.setAwardedId(awardedExamine.getAwardedId());
        if (awardedExamine==null) {
            return RestResult.failure("获奖的审核id有误，请重新检查");
        }

        Integer projectId = awardedExamine.getProjectId();
        ProjectExamineVo projectExamineVo = searchPEVoByProjectId(projectId);

        // 更新数据库中的项目文件的状态,项目文件通过审核则为
        boolean dbProjectFileStatus = updateDbProjectFileStatus(projectId, UniversityConstants.PROJECT_FILE_PASS, awardedExamine.getAwardedId());
        if (!dbProjectFileStatus) {
            return RestResult.failure("项目文件审核失败");
        }

        // 更新项目表数据库中的状态
        boolean status = updateDbStatus(UniversityConstants.PROJECT_STATUS_FINALIZE_PROJECT, projectExamineVo.getProjectName());
        if (!status) {
            return RestResult.failure("更新项目以及项目审核状态失败");
        }

        // 更新成果形式
        int row = awardedExamineMapper.updateByPrimaryKeySelective(examine);
        if (row < 1) {
            throw  new RuntimeException("审核获奖失败，请重试");
        }

        // 直接调用loadToRedis更新Redis
        AwardedProcessor bean = SpringUtil.getBean(AwardedProcessor.class);

        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            //存在事物，则注册事务同步处理
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    loadToRedis();
                    // 更新Redis中的项目、项目文件、项目审核等中的内容
                    bean.updateRedisStatus(projectId,UniversityConstants.PROJECT_STATUS_FINALIZE_PROJECT,awardedExamine.getAwardedId());
                }
            });
        }

        // 发送消息
        bean.approveSaveMessage(projectId,
                projectExamineVo.getProjectName(),
                reviewerId,
                UniversityConstants.PROJECT_ACHIEVEMENT_AWARD,
                awardedExamine.getLevelId());
        return RestResult.success("审核获奖成功");
    }

    @Override
    protected void saveMessage(AwardedExamineVo examineVo) {
        ProjectExamineVo vo = searchPEVoByProjectId(examineVo.getProjectId());
        messageService.submitFinalApplication(new Message(examineVo.getProjectId(),
                vo.getProjectName(),
                examineVo.getReviewerId(),
                UniversityConstants.PROJECT_ACHIEVEMENT_AWARD,
                examineVo.getAeId(),
                UniversityConstants.MESSAGE_STATUS_FINAL_APPLICATION));
    }

    @Override
    public Awarded insertData(Object data) {
        // 将Object转成Awarded对象
        Awarded awarded = objectMapper.convertValue(data, Awarded.class);

        ProjectExamineVo projectExamineVo = super.searchPEVoByProjectId(awarded.getProjectId());
        // 判断该项目的状态时否是4：也就是项目已经处于立项的状态
        if (!projectExamineVo.getStatusId().equals(UniversityConstants.PROJECT_STATUS_SECOND_PASS)){
            return null;
        }

        int row = awardedMapper.insert(awarded);

        if (row < 1) {
            throw new RuntimeException("上传获奖成果文件失败");
        }

        if (!super.updateDbStatus(UniversityConstants.PROJECT_STATUS_SUCCESS_PROJECT, projectExamineVo.getProjectName())) {
            throw new RuntimeException("更新数据库失败");
        }

        AwardedProcessor bean = SpringUtil.getBean(AwardedProcessor.class);
        bean.updateRedisStatus(awarded.getProjectId(),UniversityConstants.PROJECT_STATUS_SUCCESS_PROJECT, awarded.getAwardedId());

        return awarded;
    }

    @Override
    @Async
    public AwardedExamineVo generateVo(Awarded data) {
        AwardedExamineVo examineVo = new AwardedExamineVo();

        BeanUtils.copyProperties(data,examineVo);
        examineVo.setExamineStatus("未审核");
        examineVo.setApplyTime(new java.sql.Date(System.currentTimeMillis()));

        // 因为PaperExamineVo对象中有projectExamineVo对象，所以需要把projectExamineVo对象找到，根据projectId查找
        Integer projectId = data.getProjectId();
        ProjectExamineVo projectExamineVo = super.searchPEVoByProjectId(projectId);

        // 搜索负责人
        for (UserVo userVo : projectExamineVo.getTeam()) {
            if (userVo.getUserId().equals(data.getLeaderId())) {
                examineVo.setLeaderName(userVo.getUserRealname());
                break;
            }
        }

        AwardedExamine pojo = new AwardedExamine();
        BeanUtils.copyProperties(examineVo,pojo);

        int row = awardedExamineMapper.insertSelective(pojo);
        if (row < 1) {
            throw new RuntimeException("插入获奖审核失败");
        }

        // 设置普通成员变量
        examineVo.setProjectExamineVo(projectExamineVo);
        examineVo.setAeId(pojo.getAeId());

        return examineVo;
    }

    @Override
    public List<AwardedExamineVo> passedResults(List<AwardedExamineVo> list) {
        ArrayList<AwardedExamineVo> result = new ArrayList<>();
        for (AwardedExamineVo examineVo : list) {
            if (!examineVo.getExamineStatus().equals("未审核")) {
                result.add(examineVo);
            }
        }
        return result;
    }

    @Override
    public List<AwardedExamineVo> searchByUserName(List<AwardedExamineVo> list, String userName) {

        List<AwardedExamineVo> result = new ArrayList<>();
        for (AwardedExamineVo awardedExamineVo : list) {
            if (awardedExamineVo.getLeaderName()!=null && awardedExamineVo.getLeaderName().contains(userName)) {
                result.add(awardedExamineVo);
            }
        }

        return result;
    }

    @Override
    public void loadToRedis() {
        ValueOperations opsForValue = redisTemplate.opsForValue();
        List<AwardedExamine> awardedExamines = awardedExamineMapper.searchAll();

        List<AwardedExamineVo> awardedExamineVos = new ArrayList<>();

        for (AwardedExamine awardedExamine : awardedExamines) {
            AwardedExamineVo vo = new AwardedExamineVo();
            BeanUtils.copyProperties(awardedExamine, vo);

            // 通过projectId找到projectExamineVo，并且设置到PaperExamineVo中
            ProjectExamineVo projectExamineVo = searchPEVoByProjectId(awardedExamine.getProjectId());
            vo.setProjectExamineVo(projectExamineVo);

            // 设置负责人姓名
            for (UserVo userVo : projectExamineVo.getTeam()) {
                if (userVo.getUserId().equals(awardedExamine.getLeaderId())) {
                    vo.setLeaderName(userVo.getUserRealname());
                    break;
                }
            }
            // 设置申请时间
            vo.setApplyTime(awardedExamine.getApplyTime());

            awardedExamineVos.add(vo);
        }

        // 先删除Redis中的缓存
        redisTemplate.delete(repositoryName.get(getThisClassName()));

        // 放入到redis中
        opsForValue.set(repositoryName.get(getThisClassName()), awardedExamineVos);
    }

    @Override
    public List<AwardedExamineVo> searchExamineByName(String name) {
        List<AwardedExamineVo> list = getValueFromRedis(getThisClassName());

        List<AwardedExamineVo> result = new ArrayList<>();
        for (AwardedExamineVo awardedExamineVo : list) {
            if (awardedExamineVo.getAwardedName().contains(name)) {
                result.add(awardedExamineVo);
            }
        }

        return result;
    }


}
